﻿// Spun AJAX Framework
// Copyright (C) 2008 Blake Hegerle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Formality.FormalSystem.Parser
{
    using Parsing;
    using Parsing.LexicalAnalysis;
    using Parsing.ContextFree.LR;
    using Parsing.ContextFree;

    public class SentenceParser
    {
        public const string DEFINED = "\u2254";
        public const string INFERS = "\u22a8";
        public const string INFERS2 = "\u22a2";

        public const string FOR_ALL = "\u2200";
        public const string EXISTS = "\u2203";
        public const string LAMBDA = "\u03bb";
        public const string THE = "\u2129";

        public const string AND = "\u2227";
        public const string OR = "\u2228";
        public const string EQ = "\u2261";
        public const string IMPLIES = "\u2192";
        public const string NOT = "\u00ac";

        public static SentenceParser Instance { get; private set; }

        public SentenceParser()
        {
            PrecedenceRules = new PrecedenceRules();
            UnaryOperators = new UnaryOperators();
            Binders = new UnaryOperators();
            Terminals = new Terminals();

            PrecedenceRules.Add(EQ, "==");
            PrecedenceRules.Add(IMPLIES, "->");
            PrecedenceRules.Add(OR, "|");
            PrecedenceRules.Add(AND, "&");

            UnaryOperators.Add(NOT, "~");

            Binders.Add(FOR_ALL, "@");
            Binders.Add(EXISTS, "#");
            Binders.Add(LAMBDA, "\\");

            LexerBuilder = new GrammarLexer(Terminals, PrecedenceRules, Binders, UnaryOperators);

            Grammar = new GrammarBuilder(Terminals, PrecedenceRules, new SentenceFactory()).Grammar;

            Parser = new ParserFactory<Sentence>(Grammar).MakeParser();
        }

        public PrecedenceRules PrecedenceRules { get; private set; }
        public UnaryOperators UnaryOperators { get; private set; }
        public UnaryOperators Binders { get; private set; }
        public Terminals Terminals { get; private set; }
        public LexerBuilder LexerBuilder { get; private set; }
        public Grammar<Sentence> Grammar { get; private set; }
        public IParser<Sentence> Parser { get; private set; }

        public Sentence Parse(TextReader Reader)
        {
            var Sentence = Parser.Parse(LexerBuilder.NewLexer(Reader));

            Sentence.Bind(new Bindings(), 0);

            return Sentence;
        }

        public Sentence Parse(string Input)
        {
            return Parse(new StringReader(Input));
        }

        static SentenceParser()
        {
            Instance = new SentenceParser();
        }
    }
}
